<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>The Model World</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'The Model World' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../inform7n.html">Inform7</a></li><li><a href="index.html">knowledge</a></li><li><a href="index.html#5">Chapter 5: Modelling</a></li><li><b>The Model World</b></li></ul></div>
<p class="purpose">Once the assertions have all been read and reduced to inferences, we try to complete our model world.</p>

<ul class="toc"><li><a href="5-tmw.html#SP1">&#167;1. Introduction</a></li><li><a href="5-tmw.html#SP2">&#167;2. Stage I</a></li><li><a href="5-tmw.html#SP3">&#167;3. Stages II and III</a></li><li><a href="5-tmw.html#SP4">&#167;4. Stage IV</a></li><li><a href="5-tmw.html#SP5">&#167;5. Stage V</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Introduction.</b>World-building has five stages, written with Roman numerals I to V in this
source code. The logic in this section is all quite simple, but plugins are
allowed to intervene at each of the five stages, bringing domain-specific
wisdom to the process.
</p>

<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">WORLD_STAGE_I</span><span class="plain-syntax">     </span><span class="constant-syntax">1</span><span class="plain-syntax">  </span><span class="comment-syntax"> Deduce kinds for object instances</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">WORLD_STAGE_II</span><span class="plain-syntax">    </span><span class="constant-syntax">2</span><span class="plain-syntax">  </span><span class="comment-syntax"> First chance to add further properties or relationships</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">WORLD_STAGE_III</span><span class="plain-syntax">   </span><span class="constant-syntax">3</span><span class="plain-syntax">  </span><span class="comment-syntax"> Second chance to add further properties or relationships</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">WORLD_STAGE_IV</span><span class="plain-syntax">    </span><span class="constant-syntax">4</span><span class="plain-syntax">  </span><span class="comment-syntax"> Perform mutual consistency checks</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">WORLD_STAGE_V</span><span class="plain-syntax">     </span><span class="constant-syntax">5</span><span class="plain-syntax">  </span><span class="comment-syntax"> Post-game: only implementation details can be added</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">current_model_world_stage</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax"> not yet building the world model</span>

<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">World::ask_plugins_at_stage</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">World::ask_plugins_at_stage</span></span>:<br/><a href="5-tmw.html#SP2">&#167;2</a>, <a href="5-tmw.html#SP3">&#167;3</a>, <a href="5-tmw.html#SP4">&#167;4</a>, <a href="5-tmw.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">S</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">S</span><span class="plain-syntax"> != </span><span class="identifier-syntax">current_model_world_stage</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Stage mistimed"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">current_model_world_stage</span><span class="plain-syntax"> = </span><span class="identifier-syntax">S</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">PluginCalls::complete_model</span><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">World::current_building_stage</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">World::current_building_stage</span></span>:<br/>Inference Subjects - <a href="4-is.html#SP9">&#167;9</a><br/>Inferences - <a href="5-inf.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">current_model_world_stage</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. Stage I.</b>Deducing the kind of any object whose kind is not known. The core compiler
has already done the best it can, but then it lacks domain-specific
understanding. So the only business done is by plugins, which understand
certain kinds and relationships better.
</p>

<p class="commentary">Some instances change their kinds in Stage I, and this can result in further
creations by assembly sentences like "A handle is part of every door". Because
of that, Stage I takes place at the end of traverse 2 of the source text and,
uniquely, gets the opportunity to add fresh sentences to the source &mdash; thus
extending the traverse. But by the end of Stage I, all kinds are fixed, and
no further instances can be created.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">World::deduce_object_instance_kinds</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><a href="5-tmw.html#SP1" class="function-link"><span class="function-syntax">World::ask_plugins_at_stage</span></a><span class="plain-syntax">(</span><span class="constant-syntax">WORLD_STAGE_I</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Stages II and III.</b>This is an opportunity for plugins to add further properties or relationships
on the basis of contextual understanding. Two stages, and thus two opportunities,
are provided here to avoid timing issues where one plugin has to act earlier
than another.
</p>

<p class="commentary">If a plugin is going to change the compilation order of the objects (as the
spatial-model plugin does), it must do so during Stage III, not Stage II.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">World::stages_II_and_III</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">inference_subject</span><span class="plain-syntax"> *</span><span class="identifier-syntax">infs</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="reserved-syntax">inference_subject</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><a href="4-is.html#SP23" class="function-link"><span class="function-syntax">InferenceSubjects::complete_model</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><a href="5-ia.html#SP2" class="function-link"><span class="function-syntax">Properties::Appearance::reallocate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="reserved-syntax">inference_subject</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Assertions::Implications::consider_all</span><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><a href="5-tmw.html#SP1" class="function-link"><span class="function-syntax">World::ask_plugins_at_stage</span></a><span class="plain-syntax">(</span><span class="constant-syntax">WORLD_STAGE_II</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><a href="5-tmw.html#SP1" class="function-link"><span class="function-syntax">World::ask_plugins_at_stage</span></a><span class="plain-syntax">(</span><span class="constant-syntax">WORLD_STAGE_III</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">additional_property_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">set</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">set</span><span class="plain-syntax">, </span><span class="identifier-syntax">additional_property_set</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">O</span><span class="plain-syntax"> = </span><span class="identifier-syntax">set</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">owner_name</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Feeds::feed_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">O</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;k-kind&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;&lt;rp&gt;&gt;</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">additional_property</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ap</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="identifier-syntax">additional_property</span><span class="plain-syntax">, </span><span class="identifier-syntax">set</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">properties</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">property</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ap</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">attr</span><span class="plain-syntax">) </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="3-ep.html#SP4" class="function-link"><span class="function-syntax">EitherOrProperties::new_nameless</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">property_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="3-vp.html#SP4" class="function-link"><span class="function-syntax">ValueProperties::new_nameless</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">property_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">inter_pair</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterValuePairs::number_from_I6_notation</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">value_text</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">InterValuePairs::is_undef</span><span class="plain-syntax">(</span><span class="identifier-syntax">val</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">Problems::quote_stream</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">O</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">Problems::quote_stream</span><span class="plain-syntax">(2, </span><span class="identifier-syntax">ap</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">property_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">Problems::quote_stream</span><span class="plain-syntax">(3, </span><span class="identifier-syntax">ap</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">value_text</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">Untestable</span><span class="plain-syntax">));</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax">                        </span><span class="string-syntax">"A Neptune file inside one of the kits you're using says "</span>
<span class="plain-syntax">                        </span><span class="string-syntax">"that the kind '%1' should have the Inter-level property '%2' "</span>
<span class="plain-syntax">                        </span><span class="string-syntax">"set to '%3', but I can't read that value."</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
<span class="plain-syntax">                }</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">V</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">InterValuePairs::to_number</span><span class="plain-syntax">(</span><span class="identifier-syntax">val</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ap</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">attr</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">parity</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">V</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">parity</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                    </span><a href="3-ep.html#SP8" class="function-link"><span class="function-syntax">EitherOrProperties::assert</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><a href="4-ks.html#SP3" class="function-link"><span class="function-syntax">KindSubjects::from_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">), </span><span class="identifier-syntax">parity</span><span class="plain-syntax">, </span><span class="identifier-syntax">LIKELY_CE</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">R</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Rvalues::from_int</span><span class="plain-syntax">(</span><span class="identifier-syntax">V</span><span class="plain-syntax">, </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                    </span><a href="3-vp.html#SP9" class="function-link"><span class="function-syntax">ValueProperties::assert</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><a href="4-ks.html#SP3" class="function-link"><span class="function-syntax">KindSubjects::from_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">), </span><span class="identifier-syntax">R</span><span class="plain-syntax">, </span><span class="identifier-syntax">CERTAIN_CE</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                }</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_stream</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">O</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">Untestable</span><span class="plain-syntax">));</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax">                </span><span class="string-syntax">"A Neptune file inside one of the kits you're using says "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"that the kind '%1' should have certain Inter-level properties, "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"but no such kind seems to exist."</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. Stage IV.</b>This is for consistency checks or to store away useful data, but where
nothing in the model may be changed &mdash; no properties or relationships
may be added.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">World::stage_IV</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">inference_subject</span><span class="plain-syntax"> *</span><span class="identifier-syntax">infs</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="reserved-syntax">inference_subject</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><a href="4-is.html#SP24" class="function-link"><span class="function-syntax">InferenceSubjects::check_model</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="5-tmw.html#SP4_1" class="named-paragraph-link"><span class="named-paragraph">Check that properties are permitted</span><span class="named-paragraph-number">4.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="5-tmw.html#SP4_2" class="named-paragraph-link"><span class="named-paragraph">Check that properties are not contradictory</span><span class="named-paragraph-number">4.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="5-tmw.html#SP4_3" class="named-paragraph-link"><span class="named-paragraph">Check that relations are permitted</span><span class="named-paragraph-number">4.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><a href="5-tmw.html#SP1" class="function-link"><span class="function-syntax">World::ask_plugins_at_stage</span></a><span class="plain-syntax">(</span><span class="constant-syntax">WORLD_STAGE_IV</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4_1" class="paragraph-anchor"></a><b>&#167;4.1. </b>These two checks may seem a little odd. After all, we've been throwing out
impossible inferences with problem messages all along, while reading the
source text. Why not perform these checks then, too?
</p>

<p class="commentary">The answer is that both depend not only on the subject of the inferences
made, but also on what that subject inherits from. Suppose we are told:
</p>

<blockquote>
    <p>The cup is in the Yellow Cupboard. The Cupboard is lighted.</p>
</blockquote>

<p class="commentary">When we make the "lighted" inference, we know for certain what subject
it's about &mdash; the Yellow Cupboard &mdash; but not where this lives in the
inference-subject hierarchy, because that depends on the kind of the
Cupboard. Is it a room, or a container? We don't yet know (and won't until
Stage I of model-completion), so we aren't in a position to judge whether
or not it's permitted to have the property "lighted". This is why the
check is postponed until after Stage I, and it seems natural to perform
it here in Stage IV, so that we also catch any accidents due to bugs
in plugins which add inconsistent properties.
</p>

<p class="commentary">A nameless property added in Stages II and III does not need permission.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check that properties are permitted</span><span class="named-paragraph-number">4.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">inference</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inf</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">KNOWLEDGE_LOOP</span><span class="plain-syntax">(</span><span class="identifier-syntax">inf</span><span class="plain-syntax">, </span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="identifier-syntax">property_inf</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">property</span><span class="plain-syntax"> *</span><span class="identifier-syntax">prn</span><span class="plain-syntax"> = </span><a href="5-pi.html#SP8" class="function-link"><span class="function-syntax">PropertyInferences::get_property</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">inf</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">prn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">))</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-pp.html#SP2" class="function-link"><span class="function-syntax">PropertyPermissions::find</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="identifier-syntax">prn</span><span class="plain-syntax">, </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">) == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">StandardProblems::inference_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_PropertyNotPermitted</span><span class="plain-syntax">),</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="identifier-syntax">inf</span><span class="plain-syntax">, </span><span class="string-syntax">"is not allowed to exist"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">                    </span><span class="string-syntax">"because you haven't said it is. What properties something can "</span>
<span class="plain-syntax">                    </span><span class="string-syntax">"have depends on what kind of thing it is: see the Index for "</span>
<span class="plain-syntax">                    </span><span class="string-syntax">"details."</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-tmw.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_2" class="paragraph-anchor"></a><b>&#167;4.2. </b>The following contradiction checks do not apply to properties added
in Stages II and III, since those are often Inter hacks added for run-time
convenience, and don't have to follow the I7 rules.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check that properties are not contradictory</span><span class="named-paragraph-number">4.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">inference</span><span class="plain-syntax"> *</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">KNOWLEDGE_LOOP</span><span class="plain-syntax">(</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">, </span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="identifier-syntax">property_inf</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::during_stage</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">property</span><span class="plain-syntax"> *</span><span class="identifier-syntax">prn</span><span class="plain-syntax"> = </span><a href="5-pi.html#SP8" class="function-link"><span class="function-syntax">PropertyInferences::get_property</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">sign</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::get_certainty</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">) &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">sign</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax">            </span><span class="named-paragraph-container code-font"><a href="5-tmw.html#SP4_2_1" class="named-paragraph-link"><span class="named-paragraph">Look for clashes concerning this property from wider inferences</span><span class="named-paragraph-number">4.2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="3-prp.html#SP16" class="function-link"><span class="function-syntax">Properties::is_either_or</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">prn</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax">                (</span><a href="3-ep.html#SP6" class="function-link"><span class="function-syntax">EitherOrProperties::get_negation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">prn</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">prn</span><span class="plain-syntax"> = </span><a href="3-ep.html#SP6" class="function-link"><span class="function-syntax">EitherOrProperties::get_negation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">prn</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">sign</span><span class="plain-syntax"> = -</span><span class="identifier-syntax">sign</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="named-paragraph-container code-font"><a href="5-tmw.html#SP4_2_1" class="named-paragraph-link"><span class="named-paragraph">Look for clashes concerning this property from wider inferences</span><span class="named-paragraph-number">4.2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-tmw.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_2_1" class="paragraph-anchor"></a><b>&#167;4.2.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Look for clashes concerning this property from wider inferences</span><span class="named-paragraph-number">4.2.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">inference_subject</span><span class="plain-syntax"> *</span><span class="identifier-syntax">boss</span><span class="plain-syntax"> = </span><a href="4-is.html#SP11" class="function-link"><span class="function-syntax">InferenceSubjects::narrowest_broader_subject</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">boss</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">inference</span><span class="plain-syntax"> *</span><span class="identifier-syntax">wide</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">KNOWLEDGE_LOOP</span><span class="plain-syntax">(</span><span class="identifier-syntax">wide</span><span class="plain-syntax">, </span><span class="identifier-syntax">boss</span><span class="plain-syntax">, </span><span class="identifier-syntax">property_inf</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::during_stage</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wide</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">prn</span><span class="plain-syntax"> == </span><a href="5-pi.html#SP8" class="function-link"><span class="function-syntax">PropertyInferences::get_property</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wide</span><span class="plain-syntax">))</span>
<span class="plain-syntax">                    </span><span class="named-paragraph-container code-font"><a href="5-tmw.html#SP4_2_1_1" class="named-paragraph-link"><span class="named-paragraph">Check that these differently scoped inferences do not clash</span><span class="named-paragraph-number">4.2.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">boss</span><span class="plain-syntax"> = </span><a href="4-is.html#SP11" class="function-link"><span class="function-syntax">InferenceSubjects::narrowest_broader_subject</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">boss</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-tmw.html#SP4_2">&#167;4.2</a> (twice).</li></ul>
<p class="commentary firstcommentary"><a id="SP4_2_1_1" class="paragraph-anchor"></a><b>&#167;4.2.1.1. </b>It's never a problem when a vague fact about something general is contradicted
by a fact about something specific; the problem comes with something like this:
</p>

<blockquote>
    <p>A door is always open. The Marble Portal is a closed door.</p>
</blockquote>

<p class="commentary">Here the "wide" property inference, for the "door" kind, is <span class="extract"><span class="extract-syntax">CERTAIN_CE</span></span>
rather than <span class="extract"><span class="extract-syntax">LIKELY_CE</span></span>, and so we can't allow the "narrow" inference,
about the Portal, to stand.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check that these differently scoped inferences do not clash</span><span class="named-paragraph-number">4.2.1.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">abcw</span><span class="plain-syntax"> = </span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::get_certainty</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wide</span><span class="plain-syntax">); </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">abcw</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">abcw</span><span class="plain-syntax"> = -</span><span class="identifier-syntax">abcw</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">abcw</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CERTAIN_CE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">clash</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wide_sign</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::get_certainty</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wide</span><span class="plain-syntax">) &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">wide_sign</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-prp.html#SP16" class="function-link"><span class="function-syntax">Properties::is_either_or</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">prn</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">narrow_val</span><span class="plain-syntax"> = </span><a href="5-pi.html#SP8" class="function-link"><span class="function-syntax">PropertyInferences::get_value</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">wide_val</span><span class="plain-syntax"> = </span><a href="5-pi.html#SP8" class="function-link"><span class="function-syntax">PropertyInferences::get_value</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wide</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Rvalues::compare_CONSTANT</span><span class="plain-syntax">(</span><span class="identifier-syntax">narrow_val</span><span class="plain-syntax">, </span><span class="identifier-syntax">wide_val</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Clash of $P and $P\n  $I\n  $I\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">narrow_val</span><span class="plain-syntax">, </span><span class="identifier-syntax">wide_val</span><span class="plain-syntax">, </span><span class="identifier-syntax">narrow</span><span class="plain-syntax">, </span><span class="identifier-syntax">wide</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">clash</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sign</span><span class="plain-syntax"> != </span><span class="identifier-syntax">wide_sign</span><span class="plain-syntax">) </span><span class="identifier-syntax">clash</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">clash</span><span class="plain-syntax">)?</span><span class="identifier-syntax">FALSE:TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">clash</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">abcn</span><span class="plain-syntax"> = </span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::get_certainty</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">); </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">abcn</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">abcn</span><span class="plain-syntax"> = -</span><span class="identifier-syntax">abcn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">abcn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CERTAIN_CE</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                 </span><span class="named-paragraph-container code-font"><a href="5-tmw.html#SP4_2_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Issue a problem message for clash with wider inference</span><span class="named-paragraph-number">4.2.1.1.1</span></a></span>
<span class="plain-syntax">            </span><span class="reserved-syntax">else</span>
<span class="plain-syntax">                </span><a href="5-inf.html#SP4" class="function-link"><span class="function-syntax">Inferences::render_impossible</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-tmw.html#SP4_2_1">&#167;4.2.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_2_1_1_1" class="paragraph-anchor"></a><b>&#167;4.2.1.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue a problem message for clash with wider inference</span><span class="named-paragraph-number">4.2.1.1.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Checking infs $j compatible with infs $j for property $Y:\n  $I\n  $I\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="identifier-syntax">boss</span><span class="plain-syntax">, </span><span class="identifier-syntax">prn</span><span class="plain-syntax">, </span><span class="identifier-syntax">narrow</span><span class="plain-syntax">, </span><span class="identifier-syntax">wide</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">StandardProblems::infs_contradiction_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_InstanceContradiction</span><span class="plain-syntax">),</span>
<span class="plain-syntax">        </span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::where_inferred</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">narrow</span><span class="plain-syntax">), </span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::where_inferred</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wide</span><span class="plain-syntax">), </span><span class="identifier-syntax">infs</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="string-syntax">"therefore has to have two contradictory states of the same property at once"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="string-syntax">"which is impossible. When a kind's definition says that something is 'always' "</span>
<span class="plain-syntax">        </span><span class="string-syntax">"true, there is no way to override that for particular things of the kind."</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-tmw.html#SP4_2_1_1">&#167;4.2.1.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_3" class="paragraph-anchor"></a><b>&#167;4.3. </b>This is a last line of defence. Suppose we define "to connect to" as a relation
between things and things, and then write "X connects to Y". Inform must clearly
check that X and Y are both things. It does indeed make some checks along those
lines earlier on in compilation, but there are objects whose kinds are not known
until model completion time &mdash; in particular, there can be objects which might
be things or might be rooms, so that we cannot know if "X connects to Y" is
legal until after the model is completed.
</p>

<p class="commentary">But that's now! And so we make one last check, just in case.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check that relations are permitted</span><span class="named-paragraph-number">4.3</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">inference</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inf</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">POSITIVE_KNOWLEDGE_LOOP</span><span class="plain-syntax">(</span><span class="identifier-syntax">inf</span><span class="plain-syntax">, </span><span class="identifier-syntax">infs</span><span class="plain-syntax">, </span><span class="identifier-syntax">relation_inf</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> = </span><a href="4-rs.html#SP1" class="function-link"><span class="function-syntax">RelationSubjects::to_bp</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">inference_subject</span><span class="plain-syntax"> *</span><span class="identifier-syntax">left_infs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">inference_subject</span><span class="plain-syntax"> *</span><span class="identifier-syntax">right_infs</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><a href="5-ri.html#SP7" class="function-link"><span class="function-syntax">RelationInferences::get_term_subjects</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">inf</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">left_infs</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">right_infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">instance</span><span class="plain-syntax"> *</span><span class="identifier-syntax">left_instance</span><span class="plain-syntax"> = </span><a href="4-is2.html#SP1" class="function-link"><span class="function-syntax">InstanceSubjects::to_instance</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">left_infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">instance</span><span class="plain-syntax"> *</span><span class="identifier-syntax">right_instance</span><span class="plain-syntax"> = </span><a href="4-is2.html#SP1" class="function-link"><span class="function-syntax">InstanceSubjects::to_instance</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">right_infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">left_kind</span><span class="plain-syntax"> = </span><a href="2-ins.html#SP10" class="function-link"><span class="function-syntax">Instances::to_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">left_instance</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">right_kind</span><span class="plain-syntax"> = </span><a href="2-ins.html#SP10" class="function-link"><span class="function-syntax">Instances::to_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">right_instance</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">left_needed_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BinaryPredicates::term_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">right_needed_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BinaryPredicates::term_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">left_instance</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">Kinds::conforms_to</span><span class="plain-syntax">(</span><span class="identifier-syntax">left_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">left_needed_kind</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::where_inferred</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">inf</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_object</span><span class="plain-syntax">(2, </span><span class="identifier-syntax">left_instance</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(3, </span><span class="identifier-syntax">left_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(4, </span><span class="identifier-syntax">left_needed_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(5, </span><span class="identifier-syntax">right_needed_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(),</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_LateLeftTermWrongKind</span><span class="plain-syntax">));</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax">                </span><span class="string-syntax">"You wrote %1, but I think the kind of %2 is %3, and not %4, "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"which is what this relationship would need it to be. (It "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"relates %4 to %5.)"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">right_instance</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">Kinds::conforms_to</span><span class="plain-syntax">(</span><span class="identifier-syntax">right_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">right_needed_kind</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><a href="5-inf.html#SP3" class="function-link"><span class="function-syntax">Inferences::where_inferred</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">inf</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_object</span><span class="plain-syntax">(2, </span><span class="identifier-syntax">right_instance</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(3, </span><span class="identifier-syntax">right_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(4, </span><span class="identifier-syntax">left_needed_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(5, </span><span class="identifier-syntax">right_needed_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(),</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_LateRightTermWrongKind</span><span class="plain-syntax">));</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax">                </span><span class="string-syntax">"You wrote %1, but I think the kind of %2 is %3, and not %5, "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"which is what this relationship would need it to be. (It "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"relates %4 to %5.)"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-tmw.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. Stage V.</b>A final chance to add properties which may assist the run-time implementation
of whatever a plugin is concerned with, but which is not allowed to make
changes to the model as it would be understood by the author.
</p>

<p class="commentary">For example, the <a href="../runtime-module/2-ic.html" class="internal">Instance Counting (in runtime)</a> plugin adds low-level properties
to improve run-time performance, but they have no names and cannot be referred
to or accessed by code written in Inform 7; they exist at the level of Inter only.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">World::stage_V</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><a href="5-tmw.html#SP1" class="function-link"><span class="function-syntax">World::ask_plugins_at_stage</span></a><span class="plain-syntax">(</span><span class="constant-syntax">WORLD_STAGE_V</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="5-ri.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-km.html">1</a></li><li class="progresschapter"><a href="2-ins.html">2</a></li><li class="progresschapter"><a href="3-prp.html">3</a></li><li class="progresschapter"><a href="4-is.html">4</a></li><li class="progresscurrentchapter">5</li><li class="progresssection"><a href="5-inf.html">inf</a></li><li class="progresssection"><a href="5-pi.html">pi</a></li><li class="progresssection"><a href="5-ia.html">ia</a></li><li class="progresssection"><a href="5-ri.html">ri</a></li><li class="progresscurrent">tmw</li><li class="progresssection"><a href="5-tnt.html">tnt</a></li><li class="progressnext"><a href="5-tnt.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

